#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <stropts.h>
#include <sys/ioctl.h>
#include <pthread.h>

#include "global.h"
#include "constantes.h"
#include "listas.h"
#include "sockets.h"
#include "configuracion.h"
#include "NIPC.h"


int AgregarAVectorDiscosDeArchivoConfig( char *sNombre_NuevoDA ) ;
int  VerificarCompatibilidad(char *sNombre_NuevoDA , int iCC_NuevoDA, int iHH_NuevoDA , int iSS_NuevoDA);
void * HiloDeDisco (void * pNodoDisco);
void * ConsolaEsperaNuevosDiscos (void * pSocketParaArray);


extern ListConfig * listaConfig;

void * ConsolaEsperaNuevosDiscos (void * pSocketParaArray)
{

   pthread_t ID_HiloDeDisco;
   int iSocketEscuchaConexiones;
   int iSocketDisco_temporal;
   struct DiscoConocido *pNodoDisco;
   struct DiscoConocido * pAuxDisco;
   char *sNombre_NuevoDA;
   int i;
   fd_set set_socketConsola;
   InfoIPC infoIPC;
   InfoIPC responseHS;
   InfoIPC VDA;
   int iCC_NuevoDA,iHH_NuevoDA,iSS_NuevoDA;

   
   struct sockaddr_in* cliente;
   int address_size=sizeof(struct sockaddr_in);

   
   listaConfig = NULL;
   cargarConfig();
   
   iSocketEscuchaConexiones  = PrepararSocket (atoi(obtenerValor("puertoLocal")),obtenerValor("ipLocal"));   
   escuchar(iSocketEscuchaConexiones,10); 
   printf("iSocketEscuchaConexiones  %i \n",iSocketEscuchaConexiones);

   
   while(1)
   {
      printf("\nEstado del Array:\r\n");
      switch(Estado)
      {
         case INICIALIZADO:
            printf("INICIALIZADO\r\n");
         break;

         case FUERA_DE_SERVICIO:
            printf("FUERA DE SERVICIO\r\n");
         break;
      }
      switch(SubEstado)
      {
         case SINCRONIZADO:
            printf("SINCRONIZADO\r\n");
         break;

         case INCOMPLETO:
            printf("INCOMPLETO\r\n");
         break;

         case SINCRONIZANDO:
            printf("SINCRONIZANDO\r\n");
         break;
      }
      // printf("DISCOS CONECTADOS:\n");
      // pAuxDisco = ListaDiscos;
      // if(pAuxDisco == NULL)
          // printf("No hay\n");
      // while(pAuxDisco != NULL)
      // {
          // printf("%s\n", pAuxDisco->sNombre );
          // pAuxDisco = pAuxDisco->Sgt;	
      // }
		
		FD_ZERO(&set_socketConsola);
		printf("iSocketEscuchaConexiones  %i \n",iSocketEscuchaConexiones);
		FD_SET(iSocketEscuchaConexiones ,&set_socketConsola);
    
      
      select(iSocketEscuchaConexiones+1, &set_socketConsola, NULL, NULL, NULL);	

      
      if( FD_ISSET(iSocketEscuchaConexiones , &set_socketConsola ) > 0 )
      {
            
            if((iSocketDisco_temporal = accept(iSocketEscuchaConexiones,(struct sockaddr*)&cliente,&address_size))== -1) 
               return ERRORACCEPT;	
            
            printf("\nAcepte un conect, el descriptor temporal devuelto es: %i \n", iSocketDisco_temporal);     
            recibirIPC(iSocketDisco_temporal,&infoIPC);
            responseHS.payLoadLength = 0;
            strcpy(responseHS.descriptorID,infoIPC.descriptorID);			
            responseHS.payLoadDescriptor = HSOK;
            enviarIPC(iSocketDisco_temporal,&responseHS);
            recibirIPC(iSocketDisco_temporal,&VDA);    
			printf(" %s \n",VDA.payload);
            sNombre_NuevoDA=(char *)malloc(sizeof(char));
            strcpy(sNombre_NuevoDA,VDA.payload);
            recibirIPC(iSocketDisco_temporal,&VDA);
			printf(" %s \n",VDA.payload);
            iCC_NuevoDA = atoi(VDA.payload);
            recibirIPC(iSocketDisco_temporal,&VDA);
			printf(" %s \n",VDA.payload);
            iHH_NuevoDA = atoi(VDA.payload);
            recibirIPC(iSocketDisco_temporal,&VDA);
			printf(" %s \n",VDA.payload);
            iSS_NuevoDA = atoi(VDA.payload);
           
           
           
			
          
  
            
            if( INCOMPATIBLE == VerificarCompatibilidad(sNombre_NuevoDA , iCC_NuevoDA, iHH_NuevoDA, iSS_NuevoDA ) ) /*verificar si el nombre y la cantidad de sectores coincide con lo pasado por archivo config, tmb verificar si ya se conecto un disco con ese nombre*/
            {
               generarStructIPC("nada", DA_INCOMPATIBLE,&infoIPC);	
               enviarIPC(iSocketDisco_temporal,&infoIPC);
               cerrarSocket(iSocketDisco_temporal);		
               printf("INCOMPATIBLE\n");
               
               continue;
            }

            if(iCantidadDeDAConectados == MAX_CANTIDAD_DE_DA)
            {
               generarStructIPC("nada", DA_INCOMPATIBLE,&infoIPC);
               enviarIPC( iSocketDisco_temporal,&infoIPC);
               cerrarSocket(iSocketDisco_temporal);	
               printf("MAXIMA\n");
               continue;
            }

            
            pNodoDisco = malloc( sizeof(struct DiscoConocido) );
            strcpy(pNodoDisco->sNombre , sNombre_NuevoDA);
            pNodoDisco->iSocketHDAParaDA = iSocketDisco_temporal;

            pNodoDisco->ListaDeIDPedidos = NULL;
            pNodoDisco->ListaDeIDPedidos_Ult = NULL;
            CrearYConectarDosSockets( &(pNodoDisco->iSocketArrayParaHDA), &(pNodoDisco->iSocketHDAParaArray) , sIP_Local);

            pNodoDisco->Sgt = NULL;
            pNodoDisco->Ant = NULL;

            
            if(SubEstado == INCOMPLETO)  /*si todavia no se conectaron todos los discos que dice el arch de conf no hace falta que se sincronice*/
               pNodoDisco->Estado = LISTO;
            else
               pNodoDisco->Estado = SINCRONIZANDO;
             
            
            agregarAListaDeDiscos(&pNodoDisco);

            
            printf("right here \n");
            
            pthread_create(&ID_HiloDeDisco,NULL,(void*)HiloDeDisco ,(void *)pNodoDisco);	/*se crea el hilo que va a estar comunicado al disco que se agrego*/

            if(SubEstado == INCOMPLETO)
            {
               if( AgregarAVectorDiscosDeArchivoConfig(sNombre_NuevoDA) == 1) /****agrega el disco al vector, y devuelve 1 si ya se conectaron todos los discos indicados por archivo config *****/
               {
                  ArrayCompleto = VERDADERO;
                  SubEstado = SINCRONIZADO;
                  Estado = INICIALIZADO;
                  generarStructIPC("nada", INICIALIZADO,&infoIPC);
                  enviarIPC( *(int *)pSocketParaArray,&infoIPC);
               }
               else if(SubEstado == SINCRONIZADO)
                  SubEstado = SINCRONIZANDO;
            }
      
            iCantidadDeDAConectados++;
            printf("Cantidad de discos conectados %i \n",iCantidadDeDAConectados);
            generarStructIPC("nada", DA_CONECTADO_CORRECTAMENTE,&infoIPC);
            enviarIPC(iSocketDisco_temporal,&infoIPC);
            /*enviarIPC( (*(int *)pSocketParaArray),&infoIPC);*/
            
            
            
      }       
   }
}

int  VerificarCompatibilidad(char *sNombre_NuevoDA , int iCC_NuevoDA, int iHH_NuevoDA , int iSS_NuevoDA)  /*verificar si el nombre y la cantidad de sectores coincide con lo pasado por archivo config, tmb verificar si ya se conecto un disco con ese nombre*/
{
	int i;  
    /*Me fijo si ya existe un disco con ese nombre en el array*/
    for(i = 0; i < iCantidadDiscosDeArchivoConfig ; i++)
    {	
      if( (strcmp(sNombre_NuevoDA, pDiscosDeArchivoConfig[i].sNombre ) == 0) && (pDiscosDeArchivoConfig[i].Conectado == VERDADERO) )   
	    	return INCOMPATIBLE;
    }
    /*Me fijo que la cantidad de sectores del disco sea igual a la explicitada por archivo de configuracion*/
    if( (iCC_NuevoDA != glChs.cilindros) || (iHH_NuevoDA != glChs.cabezal) || (iSS_NuevoDA != glChs.sectores) )
		return INCOMPATIBLE; 

    return COMPATIBLE;
}




int AgregarAVectorDiscosDeArchivoConfig( char *sNombre_NuevoDA )  /****agrega el disco al vector, y devuelve 1 si ya se conectaron todos los discos indicados por archivo config *****/
{
    int i;
    int iTodosLosDiscosConectados;

	iTodosLosDiscosConectados=VERDADERO;
	
    for(i = 0; i < iCantidadDiscosDeArchivoConfig ; i++)
    {	
		if(strcmp(sNombre_NuevoDA, pDiscosDeArchivoConfig[i].sNombre ) == 0) 
			pDiscosDeArchivoConfig[i].Conectado = VERDADERO;

		if(pDiscosDeArchivoConfig[i].Conectado == FALSO)
			iTodosLosDiscosConectados = FALSO;	
		
	}


    if(iTodosLosDiscosConectados = VERDADERO)
		return 1;
    else 
		return 0;

	
}	







